﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Ast.Core.Settings;
using Castle.Core.Logging;
using Castle.DynamicProxy;

namespace Ast.Core.Interceptors
{
    public class ProfilingInterceptor : IInterceptor
    {
        private readonly IAstSettings _astSettings;

        [ThreadStatic]
        private static Stack<int> _stack;

        public ProfilingInterceptor(IAstSettings astSettings)
        {
            _astSettings = astSettings;

            Logger = NullLogger.Instance;
        }

        public ILogger Logger { get; set; }

        [DebuggerStepThrough]
        public void Intercept(IInvocation invocation)
        {
            if (!_astSettings.Profiling)
            {
                invocation.Proceed();
                return;
            }

            if (_stack == null) _stack = new Stack<int>();

            _stack.Push(Environment.TickCount); // push started time
            try
            {
                invocation.Proceed();
            }
            finally
            {
                var usedTime = Environment.TickCount - _stack.Pop();
                if (_stack.Count == 0 && usedTime > _astSettings.ProfilingInterval)
                {
                    Logger.WarnFormat("called using {0}ms for {1}.{2}", usedTime, invocation.TargetType.FullName, invocation.Method.Name);
                }
            }
        }
    }
}